package com.yuan.blog.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuan.blog.utils.PasswordUtils;
import com.yuan.blog.utils.UUIDUtils;
import com.yuan.blog.entity.UserEntity;
import com.yuan.blog.mapper.UserMapper;
import com.yuan.blog.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.sql.SQLException;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper,UserEntity> implements IUserService {

    @Autowired
    private UserMapper mapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private String userKey = "blog:web:user:%s";

    private Lock lock = new ReentrantLock();

    @Override
    public void register(UserEntity userEntity) throws Exception {
        // 2.密码加密
        userEntity.setPassword(PasswordUtils.hashPw(userEntity.getPassword()));
        // 3.设置用户的状态
        userEntity.setStatus(1);
        userEntity.setCreateTime(new Date());
        userEntity.setActivationCode(UUIDUtils.getId()); // 激活码
        userEntity.setType(0);
        // 4.入库
//        int save = userDao.insert(userEntity);
        save(userEntity);
    }

    @Override
    public UserEntity queryUserByActivation(String code) throws SQLException {
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("activation_code",code);
        return mapper.selectOne(wrapper);
    }

    @Override
    public UserEntity login(UserEntity userEntity) throws SQLException {
        //用户查询条件：状态为2，名字存在
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("username",userEntity.getUsername());
        wrapper.eq("status",2);
        //查找用户
        UserEntity user = mapper.selectOne(wrapper);
        if (user == null) {
            return null;
        }
        //校验密码
        if (!PasswordUtils.check(userEntity.getPassword(), user.getPassword())) {
            return null;
        }
        return user;
    }

    @Override
    public void updateHeaderUrl(Integer id, String filePath){
        UpdateWrapper<UserEntity> wrapper = new UpdateWrapper<>();
        wrapper.eq("id",id);
        UserEntity user = new UserEntity();
        user.setHeaderUrl(filePath);
        update(user,wrapper);
    }

    @Override
    public boolean updatePwdById(Integer id, String password) throws SQLException {
        String s = PasswordUtils.hashPw(password);
        UserEntity user = new UserEntity();
        user.setPassword(s);
        user.setId(id);
        return updateById(user);
    }

    //解决缓存击穿问题
    @Override
    public UserEntity queryById(Integer userId) throws Exception {

        String key = String.format(userKey,userId);
        //查询缓存
        String json = stringRedisTemplate.opsForValue().get(key);

        UserEntity userEntity = null;
        //判断缓存是否命中
        if (ObjectUtils.isEmpty(json)){

            lock.lock();
            try {
                json = stringRedisTemplate.opsForValue().get(key);
                if (ObjectUtils.isEmpty(json)){
                    //缓存没有命中,查询Mysql
                    userEntity = mapper.selectById(userId);
                    log.error("在MySQL中查询作者的数据");
                    //将结果存入数缓存
                    stringRedisTemplate.opsForValue().set(key,JSON.toJSONString(userEntity),5, TimeUnit.MINUTES);
                }else {
                    userEntity = JSON.parseObject(json,UserEntity.class);
                }
            } finally {
                lock.unlock();
            }
        }else {
            //缓存命中
            userEntity = JSON.parseObject(json,UserEntity.class);
        }


        return userEntity;
    }

    @Override
    public int updateStatus(UserEntity userEntity) throws Exception {
        UpdateWrapper<UserEntity> wrapper = new UpdateWrapper<>();
        userEntity.setStatus(2);
        return this.updateById(userEntity)?1:0;
    }
}
